library _;

import 'dart:convert';

import 'package:file_selector/file_selector.dart';
import 'package:flutter/material.dart';
import 'package:flutter_yfree/YFree.dart';
import 'package:flutter_yim/YIM.dart';
import 'package:pc/Const/IFinal.dart';
import 'package:pc/Model/Enums.dart';
import 'package:pc/Model/MessageModel.dart';
import 'package:pc/Page/Home/Chat/state.dart';
import 'package:pc/Page/Home/Chat/view.dart';
import 'package:pc/Util/App/AppUtils.dart';
import 'package:pc/Util/CompressUtils.dart';
import 'package:pc/Util/YOSS/YOSS.dart';
import 'package:pc/View/ChatFileButton.dart';
import 'package:pc/View/RightSheet.dart';
import 'package:video_compress/video_compress.dart';

part 'extensions/MessageUpload.dart';

class ChatController {
  final page = IFinal.Others.homePage;
  final state = ChatState();
  final view = ChatView();

  void init() {
    page.controller_chat!.state.scrollController.addListener(() {
      //分页
      if (!page.controller_chat!.state.isRefreshing) {
        if (page.controller_chat!.state.scrollController.offset >= page.controller_chat!.state.scrollController.position.maxScrollExtent) {
          page.setState(() => page.controller_chat!.state.isRefreshing = true);
          page.controller_chat!.loadMessages();
        }
      }
      //加载未滚动到底部时收到的消息
      if (page.controller_chat!.state.tempMessages.isNotEmpty) {
        if (page.controller_chat!.state.scrollController.offset <= 0) {
          page.controller_chat!.addMessages(messages: page.controller_chat!.state.tempMessages);
          page.controller_chat!.state.tempMessages.clear();
        }
      }
    });
  }

  void dispose() {
    state.textEditingController.dispose();
    state.focusNode.dispose();
    state.scrollController.dispose();
    state.player.dispose();
  }

  void onRecMessage(List<YIMMessage> messages) async {
    page.controller_conversation!.sendMessageReceipt();
    final userModel = (await AppUtils.readUserModel())!;
    final newMessages = messages.map((message) => MessageModel.fromYIMMessage(message, message.from == userModel.yim_user)).toList();
    final isBottom = page.controller_chat!.state.scrollController.offset <= 0; //判断原本是否在底部
    if (isBottom) {
      addMessages(messages: newMessages);
      scrollToBottom();
    } else {
      page.controller_chat!.state.tempMessages.addAll(newMessages);
    }
  }

  void onRecReceipt(String conversationID) {
    if (conversationID != page.controller_conversation!.getSelectConversation()!.conversationID) return;
    page.controller_chat!.state.messages.forEach((message) {
      message.messageState = YIMEnum_MessageState.Success_Read;
    });
    page.setState(() {});
  }

  void onRecRevoke(YIMRevokeMessage revokeMessage) {
    page.controller_chat!.state.messages.forEach((message) {
      if (revokeMessage.conversationID == page.controller_conversation!.getSelectConversation()!.conversationID && revokeMessage.messageID == message.id) {
        message.isRevoke = true;
        page.setState(() {});
        return;
      }
    });
  }

  void loadMessages() {
    YIM.messageManager.queryLocalMessages(
      conversationType: YIMEnum_ConversationType.P2P,
      conversationID: page.controller_conversation!.getSelectConversation()!.conversationID,
      time: page.controller_chat!.state.messages.isEmpty ? null : DateTime.fromMillisecondsSinceEpoch(page.controller_chat!.state.messages.last.date),
      limit: 20,
      callback: (messages) async {
        page.setState(() => page.controller_chat!.state.isRefreshing = false);
        if (messages != null && messages.isNotEmpty) {
          final userModel = (await AppUtils.readUserModel())!;
          addMessages(messages: messages.map((message) => MessageModel.fromYIMMessage(message, message.from == userModel.yim_user)).toList().reversed, isTop: true);
        }
      },
    );
  }

  void scrollToBottom({bool checkIsBottom = false}) {
    yRun(() {
      if (checkIsBottom) {
        if (page.controller_chat!.state.scrollController.offset > 0) return;
      }
      page.controller_chat!.state.scrollController.jumpTo(0);
    });
  }

  void sendMessage(Enum_MessageType messageType, String content, {Function(YIMMessage yimMessage)? onSendStart}) async {
    final userModel = (await AppUtils.readUserModel())!;
    YIM.messageManager.sendTextMessage(
      conversationType: YIMEnum_ConversationType.P2P,
      conversationID: page.controller_conversation!.getSelectConversation()!.conversationID,
      content: json.encode(
        OriginMessageModel()
          ..avatar_from = userModel.avatar
          ..avatar_to = page.controller_conversation!.getSelectConversation()!.avatar
          ..name_from = userModel.name
          ..name_to = page.controller_conversation!.getSelectConversation()!.name
          ..type = messageType
          ..content = content,
      ),
      callback_start: (yimMessage) {
        onSendStart?.call(yimMessage);
      },
      callback_finish: (isSuccess, yimMessage, code, msg) {
        page.controller_chat!.state.messages.firstWhere((element) => element.id == yimMessage.id).messageState = yimMessage.messageState;
        page.setState(() {});
      },
    );
  }

  void addMessages({required Iterable<MessageModel> messages, bool isTop = false}) {
    if (isTop) {
      page.controller_chat!.state.messages.addAll(messages);
    } else {
      page.controller_chat!.state.messages.insertAll(0, messages);
    }
    page.setState(() {});
  }

  Future<void> upload(List<XFile> files, FileType fileType) async {
    if (files.isEmpty) return;
    switch (fileType) {
      case FileType.Image:
        List<String> filePaths = [];
        for (final file in files) {
          filePaths.add(file.path);
        }
        addUploadMessages(
          filePaths,
          Enum_MessageType.Image,
          onMessagePrepare: (messageModel) async {
            page.setState(() {});
            page.controller_chat!.scrollToBottom();
            messageModel.content = await CompressUtils.compressImage(messageModel.content);
            return messageModel;
          },
        );
        break;
      case FileType.Video:
        addUploadMessages(
          [files.first.path],
          Enum_MessageType.Video,
          onMessagePrepare: (messageModel) async {
            messageModel.videoThumbnailPath = (await VideoCompress.getFileThumbnail(messageModel.content)).path;
            page.setState(() {});
            page.controller_chat!.scrollToBottom();
            messageModel.content = await CompressUtils.compressVideo(messageModel.content);
            return messageModel;
          },
        );
        break;
      default:
        break;
    }
  }

  void showSlidingMenu() {
    final width = 300.0;
    late RightSheetController rightSheetController;

    List<Widget> view_items() {
      return [
        const Padding(
          padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
          child: Text("聊天设置", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)),
        ),
        YSpacer(height: 10),
        YButton(
          width: width,
          height: 50,
          child: const Text("清空记录", style: TextStyle(color: Colors.red)),
          onTap: () {
            rightSheetController.dismiss();
            yShowBuilder("确定要清空记录吗？", () async {
              await YIM.messageManager.clearLocalMessage(YIMEnum_ConversationType.P2P, page.controller_conversation!.getSelectConversation()!.conversationID);
              page.controller_chat!.state.messages.clear();
              page.setState(() {});
              yToast("清空成功");
            }, null, true);
          },
        ),
      ];
    }

    showRightSheet(
      context: page.context,
      onCreate: (controller) => rightSheetController = controller,
      child: Container(
        width: yScreenSize().width,
        height: yScreenSize().height,
        alignment: Alignment.centerRight,
        child: Row(
          children: [
            Expanded(child: GestureDetector(onTap: () => rightSheetController.dismiss())),
            Container(
              width: width,
              height: yScreenSize().height,
              decoration: BoxDecoration(
                color: Colors.white,
                boxShadow: [BoxShadow(blurRadius: 20, spreadRadius: 0, offset: const Offset(0, -20), color: Colors.black.withAlpha(50))],
              ),
              child: ListView(
                padding: EdgeInsets.zero,
                children: view_items(),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
